﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Statistics.Distribution
{
    /// <summary>
    /// This class represents a Exponential distribution.
    /// </summary>
    [Serializable]
    public class ExponentialDistribution
    {
        /// <summary>
        /// The rate parameter of the distribution.
        /// </summary>
        private readonly double rate;

        /// <summary>
        /// Initializes a new instance of the <see cref="ExponentialDistribution"/> class.
        /// </summary>
        /// <param name="rate">The rate parameter of the distribution.</param>
        public ExponentialDistribution(double rate)
        {
            if (rate <= 0)
            {
                throw new ArgumentException("rate <= 0");
            }

            this.rate = rate;
        }

        /// <summary>
        /// Gets the rate parameter of the distribution.
        /// </summary>
        /// <value>The rate parameter of the distribution.</value>
        public double Rate
        {
            get { return this.rate; }
        }

        /// <summary>
        /// Gets the mean of the distribution.
        /// </summary>
        /// <value>The mean of the distribution.</value>
        public double Mean
        {
            get { return 1/this.rate; }
        }

        /// <summary>
        /// Gets the median of the distribution.
        /// </summary>
        /// <value>The median of the distribution.</value>
        public double Median
        {
            get { return Math.Log(2)/this.rate; }
        }

        /// <summary>
        /// Gets the mode of the distribution.
        /// </summary>
        /// <value>The mode of the distribution.</value>
        public double Mode
        {
            get { return 0; }
        }

        /// <summary>
        /// Gets the variance of the distribution.
        /// </summary>
        /// <value>The variance of the distribution.</value>
        public double Variance
        {
            get { return 1/Math.Pow(this.rate, 2); }
        }

        /// <summary>
        /// Gets the skewness of the distribution.
        /// </summary>
        /// <value>The skewness of the distribution.</value>
        public double Skewness
        {
            get { return 2; }
        }

        /// <summary>
        /// Computes the probability mass function of the exponential distribution at the specified postion x.
        /// </summary>
        /// <param name="x">The specified position x.</param>
        /// <returns>The probability mass function of the exponential distribution at the specified postion x.</returns>
        public double ProbabilityMassFunction(double x)
        {
            return this.rate*Math.Pow(Math.E, -this.rate*x);
        }

        /// <summary>
        /// Computes the cumulative distribution function of the exponential distribution at the specified postion x.
        /// </summary>
        /// <param name="x">The specified position x.</param>
        /// <returns>The cumulative distribution function of the exponential distribution at the specified postion x.</returns>
        public double CumulativeDistributionFunction(double x)
        {
            return 1 - (this.rate*Math.Pow(Math.E, -this.rate*x));
        }
    }
}